﻿using System;

using zijian666.Core.Abstractions;
namespace zijian666.Converts;

/// <summary>
/// 实现转换接口 <seealso cref="IFormatterConverterFeature"/> 的可设置组件
/// </summary>
internal class FormatterConverter : IFormatterConverterFeature
{
    /// <summary>
    /// 单例模式，不需要重复构造
    /// </summary>
    public static FormatterConverter Instance { get; } = new FormatterConverter();

    /// <inheritdoc />
    public bool TryConvert<T>(object value, out T? result)
    {
        var res = Converts.Convert<T>(value);
        result = res.GetValueOrDefalut(default);
        return res.Success;
    }

    /// <inheritdoc />
    public bool TryConvert(object value, Type type, out object? result)
    {
        var res = Converts.Convert(value, type);
        result = res.GetValueOrDefalut(default);
        return res.Success;
    }

    /// <inheritdoc />
    public object? Convert(object value, Type type) => value.Convert(type).Value;

    /// <inheritdoc />
    public object? Convert(object value, TypeCode typeCode) => typeCode switch
    {
        TypeCode.Boolean => ToBoolean(value),
        TypeCode.Byte => ToByte(value),
        TypeCode.Char => ToChar(value),
        TypeCode.DateTime => ToDateTime(value),
        TypeCode.DBNull => Convert(value, typeof(DBNull)),
        TypeCode.Decimal => ToDecimal(value),
        TypeCode.Double => ToDouble(value),
        TypeCode.Int16 => ToInt16(value),
        TypeCode.Int32 => ToInt32(value),
        TypeCode.Int64 => ToInt64(value),
        TypeCode.Object => value,
        TypeCode.SByte => ToSByte(value),
        TypeCode.Single => ToSingle(value),
        TypeCode.String => ToString(value),
        TypeCode.UInt16 => ToUInt16(value),
        TypeCode.UInt32 => ToUInt32(value),
        TypeCode.UInt64 => ToUInt64(value),
        TypeCode.Empty => throw new NotSupportedException(),
        _ => throw new NotSupportedException(),
    };

    /// <inheritdoc />
    public bool ToBoolean(object value) => value.To<bool>();
    /// <inheritdoc />
    public byte ToByte(object value) => value.To<byte>();
    /// <inheritdoc />
    public char ToChar(object value) => value.To<char>();
    /// <inheritdoc />
    public DateTime ToDateTime(object value) => value.To<DateTime>();
    /// <inheritdoc />
    public decimal ToDecimal(object value) => value.To<decimal>();
    /// <inheritdoc />
    public double ToDouble(object value) => value.To<double>();
    /// <inheritdoc />
    public short ToInt16(object value) => value.To<short>();
    /// <inheritdoc />
    public int ToInt32(object value) => value.To<int>();
    /// <inheritdoc />
    public long ToInt64(object value) => value.To<long>();
    /// <inheritdoc />
    public sbyte ToSByte(object value) => value.To<sbyte>();
    /// <inheritdoc />
    public float ToSingle(object value) => value.To<float>();
    /// <inheritdoc />
    public string? ToString(object value) => value.To<string>();
    /// <inheritdoc />
    public ushort ToUInt16(object value) => value.To<ushort>();
    /// <inheritdoc />
    public uint ToUInt32(object value) => value.To<uint>();
    /// <inheritdoc />
    public ulong ToUInt64(object value) => value.To<ulong>();
    /// <inheritdoc />
    public dynamic ToDynamic(object value) => value.ToDynamic();
}
